import Vue from 'vue'
import router from './router'
import store from './store'

import NProgress from 'nprogress' // progress bar
import '@/components/NProgress/nprogress.less' // progress bar custom style
import notification from 'ant-design-vue/es/notification'
import { setDocumentTitle, domTitle } from '@/utils/domUtil'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import indexOf from 'lodash.indexof'
import { i18nRender } from '@/locales' // i18n

NProgress.configure({ showSpinner: false }) // NProgress Configuration

const whiteList = ['login', 'register', 'registerResult'] // no redirect whitelist
const defaultRoutePath = '/dashboard/workplace'

/**
 * @param to: Route: 即将要进入的目标 路由对象
 * @param from: Route: 当前导航正要离开的路由
 * @param next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
 * @see https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%89%8D%E7%BD%AE%E5%AE%88%E5%8D%AB
 */
router.beforeEach((to, from, next) => {
  NProgress.start() // start progress bar
  // meta & title
  to.meta && typeof to.meta.title !== 'undefined' && setDocumentTitle(`${i18nRender(to.meta.title)} - ${domTitle}`)
  // 已登录
  if (Vue.ls.get(ACCESS_TOKEN)) {
    /* has token */
    if (to.path === '/user/login') {
      // 如果已登录，url为登录页面，则直接跳转至默认首页
      next({ path: defaultRoutePath })
      NProgress.done()
    } else {
      // 角色
      if (store.getters.roles.length === 0) {
        store
          .dispatch('GetInfo')
          .then(res => {
            const roles = res.data && res.data.role
            console.log('roles', roles)
            store.dispatch('GenerateRoutes', { roles }).then(() => {
              // 根据roles权限生成可访问的路由表
              // 动态添加可访问路由表
              router.addRoutes(store.getters.addRouters)
              const redirect = decodeURIComponent(from.query.redirect || to.path)
              if (to.path === redirect) {
                // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
                next({ ...to, replace: true })
              } else {
                // 跳转到目的路由
                next({ path: redirect })
              }
            })
          })
          .catch(() => {
            notification.error({
              message: '错误',
              description: '请求用户信息失败，请重试'
            })
            store.dispatch('Logout').then(() => {
              next({ path: '/user/login', query: { redirect: to.fullPath } })
            })
          })
      } else {
        next()
      }
    }
  } else {
    // 未登录
    if (whiteList.includes(to.name)) {
      // 在免登录白名单，直接进入
      next()
    } else {
      next({ path: '/user/login', query: { redirect: to.fullPath } })
      NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
    }
  }
})

router.afterEach(() => {
  NProgress.done() // finish progress bar
})

/**
 * Action 权限指令
 * 指令用法：
 *  - 在需要控制 action 级别权限的组件上使用 v-action:[method] , 如下：
 *    <i-button v-action:add >添加用户</a-button>
 *    <a-button v-action:delete>删除用户</a-button>
 *    <a v-action:edit @click="edit(record)">修改</a>
 *
 *  - 当前用户没有权限时，组件上使用了该指令则会被隐藏
 *  - 当后台权限跟 pro 提供的模式不同时，只需要针对这里的权限过滤进行修改即可
 *
 *  @see https://github.com/sendya/ant-design-pro-vue/pull/53
 */
const action = Vue.directive('action', {
  /**
   * 钩子函数 bind: 只调用一次，指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
   * @param el 指令所绑定的元素，可以用来直接操作 DOM 。
   * @param binding 一个对象，包含以下属性
   * @param vnode Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
   * @see https://cn.vuejs.org/v2/guide/custom-directive.html
   */
  bind: function(el, binding, vnode) {
    const actionName = binding.arg // binding.arg 传给指令的参数
    const roles = store.getters.roles // 角色权限
    console.log('roles', roles)
    // const elVal = vnode.context.$route.meta.permission
    // const permissionId = elVal instanceof String && [elVal] || elVal
    if (indexOf(roles, actionName) === -1) {
      ;(el.parentNode && el.parentNode.removeChild(el)) || (el.style.display = 'none')
    }
    // roles.permissions.forEach(p => {
    //   if (!permissionId.includes(p.permissionId)) {
    //     return
    //   }
    //   if (p.actionList && !p.actionList.includes(actionName)) {
    //     el.parentNode && el.parentNode.removeChild(el) || (el.style.display = 'none')
    //   }
    // })
  }
})

export { action }
